/*
 * SpeciesUtils.cpp
 *
 *  Created on: 22 Aug 2011
 *      Author: Allan
 */

#include "SpeciesUtils.h"

// C++ includes
#include <set>

// Boost includes
#include <boost/foreach.hpp>

// GeoReact includes
#include "StringUtils.h"
#include "../Database.h"
#include "../Utilities/Algorithms.h"

const vector<string> FilterIons(const vector<string>& species)
{
	// The list of aqueous ions from the given list of species
	vector<string> ions;
	
	// Loop over all the species and check which of them is an aqueous ion
	BOOST_FOREACH(const string& s, species)
		if(s.find("+") != s.npos || s.find("-") != s.npos)
			ions.push_back(s);
	
	return ions;
}

const vector<string> FilterComplexes(const vector<string>& species)
{
	// Get an instance of the database
	const Database& db = Database::GetInstance();
	
	// The list of aqueous complexes from the given list of (species)
	vector<string> complexes;
	
	// Loop over all the species and check which of them is an aqueous complex
	BOOST_FOREACH(auto s, species)
		if(db.FindComplexInfo(s))
			complexes.push_back(s);
	
	return complexes;
}

const vector<string> FilterBasisSpecies(const vector<string>& species)
{
	return FilterSpecies(species, {"basis"});
}

const vector<string> FilterSecondarySpecies(const vector<string>& species)		
{
	return RemoveSpecies(species, {"basis"});
}

const vector<string> FilterSpecies(const vector<string>& species, const vector<string>& tags)
{
	// The subset of the given species that have any of the given tags
	vector<string> newSpecies;
	
	// Loop over all the given species 
	BOOST_FOREACH(const string& s, species)
		if(Database::GetInstance().GetSpeciesInfo(s).HasAnyTag(tags))
			newSpecies.push_back(s);
			
	return newSpecies;
}

const vector<string> RemoveSpecies(const vector<string>& species, const vector<string>& tags)
{
	// The subset of the given species that does not have any of the given tags
	vector<string> newSpecies;
	
	// Loop over all the given species 
	BOOST_FOREACH(const string& s, species)
		if(!Database::GetInstance().GetSpeciesInfo(s).HasAnyTag(tags))
			newSpecies.push_back(s);
			
	return newSpecies;
}

const double ElectricalCharge(const string& ion)
{
	vector<string> words = Split(ion, "[]");
	
	if(words.size() == 1) return 0;
	
	if(words[1] == "+") return +1;
	if(words[1] == "-") return -1;
	
	const string strCharge = {words[1][1], words[1][0]};
	
	const double charge = atof(strCharge.c_str());
	
	return charge;
}
